 1.Hive join的三种方式
   
   1).common join
   普通连接，在SQL中不特殊指定连接方式使用的都是这种普通连接。
   缺点：性能较差(要将数据分区，有shuffle)
   优点：操作简单，普适性强
   2).map join
   map端连接，与普通连接的区别是这个连接中不会有reduce阶段存在，连接在map端完成
   适用场景：大表与小表连接，小表数据量应该能够完全加载到内存，否则不适用
   优点：在大小表连接时性能提升明显，
   备注：Hive 0.6 的时候默认认为写在select 后面的是大表，前面的是小表， 或者使
用 /*+mapjoin(map_table) */ 提示进行设定。select a., b.* from a join b on a.id =
b.id【要求小表在前，大表之后】
     hive 0.7 的时候这个计算是自动化的，它首先会自动判断哪个是小表，哪个是大表，
这个参数由（hive.auto.convert.join=true）来控制，然后控制小表的大小由
（hive.smalltable.filesize=25000000）参数控制（默认是25M），当小表超过这个
大小，hive 会默认转化成common join。
     Hive 0.8.1 ，hive.smalltable.filesize => hive.mapjoin.smalltable.filesize
     缺点：使用范围较小，只针对大小表且小表能完全加载到内存中的情况。
   3).bucket map join
   分桶连接：Hive 建表的时候支持hash 分区通过指定clustered by (col_name,xxx )
into number_buckets buckets 关键字.当连接的两个表的join key 就是bucket column 
的时候，就可以通过设置hive.optimize.bucketmapjoin= true 来执行优化。
   原理：通过两个表分桶在执行连接时会将小表的每个分桶映射成hash表，每个task
节点都需要这个小表的所有hash表，但是在执行时只需要加载该task所持有大表分桶对
应的小表部分的hash表就可以，所以对内存的要求是能够加载小表中最大的hash块即可。
   注意点：小表与大表的分桶数量需要是倍数关系，这个是因为分桶策略决定的，分桶
时会根据分桶字段对桶数取余后决定哪个桶的，所以要保证成倍数关系。
   优点：比map join对内存的要求降低，能在逐行对比时减少数据计算量（不用比对
小表全量）
   缺点：只适用于分桶表

